﻿/**************************************************************
*作者：Leon
*创建时间：2022/4/5 15:34:47
**************************************************************/
using Microsoft.Toolkit.Mvvm.ComponentModel;
using Microsoft.Toolkit.Mvvm.DependencyInjection;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;

namespace Lad.DrawProject.Controls;

public interface IDiagramServiceProvider : INotifyPropertyChanged
{
    DrawMode DrawMode { get; set; }
    CursorMode CursorMode { get; set; }
    void ResetDrawMode();


    /// <summary>
    /// 当前鼠标点
    /// </summary>
    Point CurrentPoint { get; set; }

    /// <summary>
    /// 当前颜色
    /// </summary>
    Color CurrentColor { get; set; }

    /// <summary>
    /// 复制默认颜色
    /// </summary>
    /// <returns></returns>
    IColorViewModel CopyDefaultColorViewModel();

    /// <summary>
    /// 复制默认字体
    /// </summary>
    /// <returns></returns>
    IFontViewModel CopyDefaultFontViewModel();

    IBaseCanvasViewModel? CanvasViewModel { get; set; }
    QuickThemeViewModel QuickThemeViewModel { get; }
    internal ActionManager ActionManager { get; }
}

public class DiagramServicesProvider : ObservableObject, IDiagramServiceProvider
{
    private static readonly Lazy<DiagramServicesProvider> instance = new(() => new DiagramServicesProvider());
    public static DiagramServicesProvider Instance
    {
        get { return instance.Value; }
    }

    private DrawMode _DrawMode;

    public DrawMode DrawMode
    {
        get { return _DrawMode; }
        set { SetProperty(ref _DrawMode, value); }
    }

    private CursorMode _CursorMode;

    public CursorMode CursorMode
    {
        get { return _CursorMode; }
        set { SetProperty(ref _CursorMode, value); }
    }

    private Point _CurrentPoint;

    public Point CurrentPoint
    {
        get { return _CurrentPoint; }
        set { SetProperty(ref _CurrentPoint, value); }
    }

    private Color _CurrentColor;

    public Color CurrentColor
    {
        get { return _CurrentColor; }
        set { SetProperty(ref _CurrentColor, value); }
    }

    private IColorViewModel _Color;

    public IColorViewModel Color
    {
        get { return _Color; }
        set { SetProperty(ref _Color, value); }
    }
    private IFontViewModel _Font;
    private readonly ActionManager ActionManager;

    public IFontViewModel Font
    {
        get { return _Font; }
        set { SetProperty(ref _Font, value); }
    }

   public IBaseCanvasViewModel? CanvasViewModel { get; set; }

    ActionManager IDiagramServiceProvider.ActionManager => ActionManager;

    public void ResetDrawMode()
    {
        DrawMode = DrawMode.Normal;
    }

    /// <summary>
    /// 复制默认颜色
    /// </summary>
    /// <returns></returns>
    public IColorViewModel CopyDefaultColorViewModel()
    {
        var viewModel = _Color;
        return CopyHelper.Mapper(viewModel);
    }

    /// <summary>
    /// 复制默认字体
    /// </summary>
    /// <returns></returns>
    public IFontViewModel CopyDefaultFontViewModel()
    {
        var viewModel = _Font;
        return CopyHelper.Mapper<FontViewModel, IFontViewModel>(viewModel)!;
    }

    private QuickThemeViewModel _QuickThemeViewModel;

    public QuickThemeViewModel QuickThemeViewModel
    {
        get { return _QuickThemeViewModel; }
        set { SetProperty(ref _QuickThemeViewModel, value); }
    }

    public DiagramServicesProvider()
    {
        ActionManager = new ActionManager();
        _QuickThemeViewModel = new QuickThemeViewModel();
        _QuickThemeViewModel.PropertyChanged += (sender, e) => OnPropertyChanged(e);
        var quickThemes = _QuickThemeViewModel.QuickThemes.Last();
        _Color = quickThemes.ColorViewModel!;
        _Font = quickThemes.FontViewModel!;
    }

}


#region 绘图模式
public enum DrawMode
{
    Normal = 0,
    Line = 1,
    Rectangle = 2,
    Ellipse = 3,
    Polyline = 4,
    Polygon = 5,
    DirectLine = 6,
    ConnectingLine = 10,
    CornerConnectingLine = 11,
    BoundaryConnectingLine = 12,
    RadiusConnectingLine = 13,
    Text = 20,
}
public enum CursorMode
{
    Normal = 0,
    Format = 1,
    Move = 2,
}


#endregion

public class CopyHelper
{
    /// <summary>
    /// 深克隆
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static T? DeepCopyByReflect<T>(T? obj)
    {
        //如果是字符串或值类型则直接返回
        if (obj == null || obj is string || obj.GetType().IsValueType) return obj;

        object? retval = Activator.CreateInstance(obj.GetType());
        if (retval == null)
            return default;

        FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
        foreach (FieldInfo field in fields)
        {
            try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); }
            catch { }
        }
        return (T)retval;
    }

    /// <summary>
    /// 自动复制
    /// </summary>
    /// <typeparam name="TParent">父对象类型</typeparam>
    /// <typeparam name="TChild">子类型</typeparam>
    /// <param name="parent">父对象实例</param>
    /// <returns></returns>
    public static TChild AutoCopy<TParent, TChild>(TParent parent) where TChild : TParent, new()
    {
        TChild child = new();
        var ParentType = typeof(TParent);
        var Properties = ParentType.GetProperties();
        foreach (var Propertie in Properties)
        {
            //循环遍历属性
            if (Propertie.CanRead && Propertie.CanWrite)
            {
                //进行属性拷贝
                Propertie.SetValue(child, Propertie.GetValue(parent, null), null);
            }
        }
        return child;
    }

    /// <summary>
    /// 自动复制
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="source"></param>
    /// <returns></returns>
    public static T? AutoCopy<T>(T? source) where T : new()
    {
        //如果是字符串或值类型则直接返回
        if (source == null || source is string || source.GetType().IsValueType) return source;

        T target = new();
        var Properties = typeof(T).GetProperties();
        foreach (var Propertie in Properties)
        {
            //循环遍历属性
            if (Propertie.CanRead && Propertie.CanWrite)
            {
                //进行属性拷贝
                Propertie.SetValue(target, Propertie.GetValue(source, null), null);
            }
        }
        return target;
    }

    public static T? DeepCopy<T>(T? obj)
    {
        //如果是字符串或值类型则直接返回
        if (obj == null || obj is string || obj.GetType().IsValueType) return obj;

        object retval;
        using (MemoryStream ms = new())
        {
            XmlSerializer xml = new(typeof(T));
            xml.Serialize(ms, obj);
            ms.Seek(0, SeekOrigin.Begin);
            retval = xml.Deserialize(ms);
            ms.Close();
        }
        return (T)retval;
    }

    /// <summary>
    /// 反射实现两个类的对象之间相同属性的值的复制
    /// 适用于初始化新实体
    /// </summary>
    /// <typeparam name="D">返回的实体</typeparam>
    /// <typeparam name="S">数据源实体</typeparam>
    /// <param name="s">数据源实体</param>
    /// <returns>返回的新实体</returns>
    public static D Mapper<D, S>(S s!!)
    {
        D d = Activator.CreateInstance<D>(); //构造新实例
        try
        {
            var Types = s.GetType();//获得类型  
            var Typed = typeof(D);
            foreach (PropertyInfo sp in Types.GetProperties().Where(p => p.CanRead))//获得类型的属性字段  
            {
                foreach (PropertyInfo dp in Typed.GetProperties().Where(p => p.CanWrite))
                {
                    if (dp.Name == sp.Name && dp.PropertyType == sp.PropertyType)//判断属性名是否相同  
                    {
                        dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性  
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        return d;
    }



    public static ColorViewModel Mapper(IColorViewModel s)
    {
        var d = Mapper<ColorViewModel, IColorViewModel>(s);

        d.LineColor = Mapper<ColorObject, IColorObject>(s.LineColor);
        d.FillColor = Mapper<ColorObject, IColorObject>(s.FillColor);
        d.LineColor.GradientStop = DeepCopy(s.LineColor.GradientStop);
        d.FillColor.GradientStop = DeepCopy(s.FillColor.GradientStop);
        return d;
    }



    public static void CopyPropertyValue(IColorViewModel s, IColorViewModel d, string? propertyName = null)
    {
        if (propertyName == "LineColor")
        {
            CopyPropertyValue(s.LineColor, d.LineColor);
            d.LineColor.GradientStop = CopyHelper.DeepCopy<ObservableCollection<GradientStop>>(s.LineColor.GradientStop);
        }
        else if (propertyName == "FillColor")
        {
            CopyPropertyValue(s.FillColor, d.FillColor);
            d.FillColor.GradientStop = CopyHelper.DeepCopy<ObservableCollection<GradientStop>>(s.FillColor.GradientStop);
        }
        else
        {
            CopyPropertyValue((object)s, (object)d, propertyName);
        }

    }

    public static void CopyPropertyValue(object s, object d, string? propertyName = null)
    {
        try
        {
            var Types = s.GetType();//获得类型  
            var Typed = d.GetType();
            var sps = Types.GetProperties().Where(p => p.CanRead && (string.IsNullOrEmpty(propertyName) || p.Name == propertyName));//获得类型的属性字段  
            var dps = Typed.GetProperties().Where(p => p.CanWrite && (string.IsNullOrEmpty(propertyName) || p.Name == propertyName));

            foreach (PropertyInfo sp in sps)//获得类型的属性字段  
            {
                foreach (PropertyInfo dp in dps)
                {
                    if (dp.Name == sp.Name && dp.PropertyType == sp.PropertyType)//判断属性名是否相同  
                    {
                        dp.SetValue(d, sp.GetValue(s, null), null);//获得s对象属性的值复制给d对象的属性  
                    }
                }
            }

        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}
